Skip to content

[#148] Add archive stories with sidebar toggle#151

Merged
realproject7 merged 3 commits intomainfrom
task/148-archive-stories
Apr 23, 2026
Merged

[#148] Add archive stories with sidebar toggle#151
realproject7 merged 3 commits intomainfrom
task/148-archive-stories

Conversation

@realproject7
Copy link
Copy Markdown
Owner

Summary

  • Fixes [Feature] Archive stories with sidebar toggle #148 — no way to organize old/completed stories
  • Archive button on terminal tab bar for confirmed stories (with structure.md)
  • Confirmation dialog before archiving
  • Story folders moved to ~/.plotlink-ows/stories/.archived/
  • Archives toggle at bottom of sidebar switches to archive view
  • Archive view shows archived stories with per-story Restore button
  • Back button returns to normal stories view
  • Untitled sessions show Cancel (not Archive)

Changes

  • app/routes/stories.ts — Added archive/restore/archived-list endpoints
  • app/web/components/TerminalPanel.tsx — Archive button, confirmation dialog, onArchiveStory prop
  • app/web/components/StoryBrowser.tsx — Archive view toggle, archived stories list, restore functionality
  • app/web/components/StoriesPage.tsxhandleArchiveStory callback
  • app/web/dist/ — Rebuilt frontend
  • package.json — Version bump 1.0.12 → 1.0.13

Test plan

  • npm run typecheck — passes
  • npm run app:build — passes
  • Archive button visible for confirmed stories, not untitled
  • Click Archive → confirmation dialog → story moved to .archived/
  • Archived story removed from main sidebar
  • Click "Archives" toggle → shows archived stories with Restore
  • Click Restore → story returns to main list
  • Click Back → returns to normal stories view

🤖 Generated with Claude Code

Backend:
- POST /api/stories/archive — moves story to .archived/ subdirectory
- POST /api/stories/restore — moves story back from .archived/
- GET /api/stories/archived — lists archived stories
- Only stories with structure.md can be archived

Frontend:
- TerminalPanel: Archive button on tab bar for confirmed stories,
  confirmation dialog before archiving
- StoryBrowser: Archives toggle at bottom, archive view with Restore
  buttons per story, Back button to return to normal view
- StoriesPage: handleArchiveStory calls archive API, clears selection

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@realproject7
Copy link
Copy Markdown
Owner Author

Review — @re2

✅ APPROVED

Well-structured feature across all layers:

Backend (stories.ts):

  • ARCHIVED_DIR = STORIES_DIR/.archived — within same parent, no EXDEV risk on rename
  • /archive validates structure.md exists before archiving — correct per acceptance criteria
  • /restore checks for conflicts (409 if story name already exists in main)
  • /archived reuses scanStory() for consistent data shape
  • .archived naturally excluded from main listing by the existing . prefix filter

Frontend:

  • TerminalPanel — Archive button for confirmed stories, Cancel for untitled. Ternary replaces the old _new_-only conditional cleanly. Archive confirmation uses accent color (non-destructive action), discard uses error color.

  • StoryBrowser — Archives toggle at bottom, full archive view with Back + per-story Restore. Loads archived stories on toggle (no unnecessary polling).

  • StoriesPagehandleArchiveStory clears selection when archiving the active story. Correct.

  • On archive confirm: destroySession then onArchiveStory — correct order (kill terminal, then move folder).

Version 1.0.13 correct. CI pending, no concerns.

Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

The archive APIs and sidebar archive view are broadly aligned with issue #148, but the terminal Archive action is not gated to confirmed stories and the archive flow destroys the active terminal before the archive request has succeeded.

Findings

  • [high] The Archive button is shown for any non-untitled storyName when onArchiveStory is present, without checking whether the story has structure.md. The acceptance criteria require the button only for confirmed stories and only stories with structure.md can be archived. For an unconfirmed non-_new_ story, the UI presents Archive, shows confirmation, then the backend rejects the request.

    • File: app/web/components/TerminalPanel.tsx:426
    • Suggestion: Pass confirmed-story state into TerminalPanel from the story metadata, or have TerminalPanel fetch/check story details, and render Archive only when hasStructure is true. Keep Cancel for _new_ sessions.
  • [medium] Confirming Archive calls destroySession(name) before onArchiveStory?.(name), so the terminal session is removed and the PTY is killed even if the archive API fails. This is especially visible with the missing confirmed-story gate, but it can also happen on API conflicts or filesystem errors, leaving the story unarchived while its active terminal was closed.

    • File: app/web/components/TerminalPanel.tsx:506
    • File: app/web/components/StoriesPage.tsx:278
    • Suggestion: Make the archive callback return success/failure and only destroy/clear the terminal after the archive endpoint returns ok, or move the teardown into StoriesPage after a successful archive.

Decision

Requesting changes. The main archive mechanics are present, but the PR does not yet meet the confirmed-story-only requirement and has unsafe failure sequencing for the archive action.

- Archive button only shows for stories with structure.md via
  confirmedStories prop (polled every 5s from stories API)
- Archive API called first in TerminalPanel; terminal session only
  destroyed after successful response
- StoriesPage no longer calls archive API (TerminalPanel handles it)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@realproject7
Copy link
Copy Markdown
Owner Author

Re-review — @re2

✅ APPROVED

Both issues from @re1 fixed:

  1. Archive gatingconfirmedStories?.has(storyName) correctly limits Archive button to stories with structure.md. Confirmed stories polled every 5s via StoriesPage.
  2. Safe teardown order — Archive button handler now awaits the archive API and only calls destroySession + onArchiveStory on res.ok. Failed archive leaves terminal intact.

No new concerns.

Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: REQUEST CHANGES

Summary

The latest fixes address the prior frontend issues: Archive is now gated on confirmed stories and terminal teardown happens only after archive API success. There is still a backend routing blocker that prevents the Archives view from reliably loading archived stories.

Findings

  • [high] GET /api/stories/archived is registered after the existing dynamic GET /api/stories/:name route. Because Hono executes matching handlers in registration order, a request to /api/stories/archived can be handled by /:name as a story named archived before the archived-list handler is reached, so the Archives view will receive the single-story 404/response instead of { stories: [...] }.
    • File: app/routes/stories.ts:90
    • File: app/routes/stories.ts:274
    • Suggestion: Register static collection routes like /archived, /archive, and /restore before dynamic /:name and /:name/:file routes, or change the archived listing path so it cannot collide with /:name.

Decision

Requesting changes. The frontend fixes look good, but the archive listing endpoint must be reachable for the sidebar Archives view to satisfy issue #148.

Static routes (GET /archived, POST /archive, POST /restore) must be
registered before the dynamic GET /:name handler, otherwise Hono
matches 'archived' as a story name parameter.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@realproject7
Copy link
Copy Markdown
Owner Author

Re-review (2) — @re2

✅ APPROVED

Route ordering fixed: static archive routes (GET /archived, POST /archive, POST /restore) now registered before dynamic GET /:name handler. No collision risk. Previous approval stands.

Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: COMMENT

Summary

The latest push fixes the backend route ordering issue: static archive routes are now registered before the dynamic /:name story route. The previous frontend findings are also addressed.

Findings

  • No remaining code blockers found in the updated diff.
  • lint-and-typecheck is still pending on the current head commit, so build/type status is not yet confirmed.

Decision

No code blockers from re1 after the fixes. Holding final approval until the current PR check finishes successfully.

Copy link
Copy Markdown
Collaborator

@project7-interns project7-interns left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: APPROVE

Summary

The PR now satisfies issue #148: confirmed stories can be archived with confirmation, archived stories are hidden from the main sidebar and available in the Archives view, restore is supported, and untitled sessions keep Cancel rather than Archive.

Findings

  • No blocking findings.
  • Previous issues were addressed: Archive is gated to stories with structure.md, terminal teardown happens only after archive success, and static archive routes are registered before dynamic story routes.
  • lint-and-typecheck passes on the current head commit.

Decision

Approved. The implementation meets the acceptance criteria and the required check is green.

@realproject7 realproject7 merged commit e7b8d14 into main Apr 23, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] Archive stories with sidebar toggle

2 participants